#pragma once

#include "Class.h"

#include "Classifier.h"
#include "Extension.h"
#include "Operation.h"
#include "Property.h"
#include "Reception.h"

namespace uml {

const bool Class::isAbstract_default_ = false;
const bool Class::isActive_default_ = false;
Class::Class(const QString& umlType)
    : Classifier(umlType) {}

void Class::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    Classifier::fromJson(json, errorList);
    BehavioredClassifier::fromJson(json, errorList);
    EncapsulatedClassifier::fromJson(json, errorList);
    JsonSerializable::fromJsonArray(extensions_, "extensions", json, errorList);
    isAbstract_ = json.value("isAbstract").toBool(isAbstract_default_);
    isActive_ = json.value("isActive").toBool(isActive_default_);
    JsonSerializable::fromJsonArray(nestedClassifiers_, "nestedClassifiers", json, errorList);
    JsonSerializable::fromJsonArray(ownedAttributes_, "ownedAttributes", json, errorList);
    JsonSerializable::fromJsonArray(ownedOperations_, "ownedOperations", json, errorList);
    JsonSerializable::fromJsonArray(ownedReceptions_, "ownedReceptions", json, errorList);
    JsonSerializable::fromJsonArray(superClasses_, "superClasses", json, errorList);
}

void Class::toJson(QJsonObject& json) {
    Classifier::toJson(json);
    BehavioredClassifier::toJson(json);
    EncapsulatedClassifier::toJson(json);
    JsonSerializable::toJsonArray(extensions_, "extensions", json);
    if (isAbstract_ != isAbstract_default_) {
        json.insert("isAbstract", isAbstract_);
    }
    if (isActive_ != isActive_default_) {
        json.insert("isActive", isActive_);
    }
    JsonSerializable::toJsonArray(nestedClassifiers_, "nestedClassifiers", json);
    JsonSerializable::toJsonArray(ownedAttributes_, "ownedAttributes", json);
    JsonSerializable::toJsonArray(ownedOperations_, "ownedOperations", json);
    JsonSerializable::toJsonArray(ownedReceptions_, "ownedReceptions", json);
    JsonSerializable::toJsonArray(superClasses_, "superClasses", json);
}

/// <summary>
/// extensions getter
/// This property is used when the Class is acting as a metaclass. It references the
/// Extensions that specify additional properties of the metaclass. The property is
/// derived from the Extensions whose memberEnds are typed by the Class.
/// </summary>
vector<shared_ptr<Extension>>& Class::extensions() {
    return extensions_;
}

/// <summary>
/// isAbstract getter
/// If true, the Class does not provide a complete declaration and cannot be
/// instantiated. An abstract Class is typically used as a target of Associations or
/// Generalizations.
/// </summary>
bool Class::isAbstract() const {
    return isAbstract_;
}

/// <summary>
/// isAbstract setter
/// If true, the Class does not provide a complete declaration and cannot be
/// instantiated. An abstract Class is typically used as a target of Associations or
/// Generalizations.
/// </summary>
void Class::setIsAbstract(bool value) {
    isAbstract_ = value;
}

/// <summary>
/// isActive getter
/// Determines whether an object specified by this Class is active or not. If true,
/// then the owning Class is referred to as an active Class. If false, then such a
/// Class is referred to as a passive Class.
/// </summary>
bool Class::isActive() const {
    return isActive_;
}

/// <summary>
/// isActive setter
/// Determines whether an object specified by this Class is active or not. If true,
/// then the owning Class is referred to as an active Class. If false, then such a
/// Class is referred to as a passive Class.
/// </summary>
void Class::setIsActive(bool value) {
    isActive_ = value;
}

/// <summary>
/// nestedClassifiers getter
/// The Classifiers owned by the Class that are not ownedBehaviors.
/// </summary>
vector<shared_ptr<Classifier>>& Class::nestedClassifiers() {
    return nestedClassifiers_;
}

/// <summary>
/// ownedAttributes getter
/// The attributes (i.e., the Properties) owned by the Class.
/// </summary>
vector<shared_ptr<Property>>& Class::ownedAttributes() {
    return ownedAttributes_;
}

/// <summary>
/// ownedOperations getter
/// The Operations owned by the Class.
/// </summary>
vector<shared_ptr<Operation>>& Class::ownedOperations() {
    return ownedOperations_;
}

/// <summary>
/// ownedReceptions getter
/// The Receptions owned by the Class.
/// </summary>
vector<shared_ptr<Reception>>& Class::ownedReceptions() {
    return ownedReceptions_;
}

/// <summary>
/// superClasses getter
/// The superclasses of a Class, derived from its Generalizations.
/// </summary>
vector<shared_ptr<Class>>& Class::superClasses() {
    return superClasses_;
}

} // namespace uml
